//
//  UXLogv.m
//  ubixar-framework
//
//  Created by Demis Bellot on 18/04/2009.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "UXLog.h"

#ifdef UX_LOG_LEVEL
NSUInteger UX_LOG_LEVELS	= UX_LOG_LEVEL;
#else
NSUInteger UX_LOG_LEVELS	= UXLogLevelAll;
#endif

UInt64 UX_LOG_LOGGERS		= UXLoggerAll;

/*
#define LP_ARGS __builtin_apply_args()
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... ) 
#endif
*/

NSString* _GetLogLevelName(UXLogLevel logLevel)
{
	switch (logLevel) 
	{
		case UXLogLevelNone:
			return @"NONE";
		case UXLogLevelAll:
			return @"ALL";
		case UXLogLevelDebug:
			return @"DEBUG";
		case UXLogLevelInfo:
			return @"INFO";
		case UXLogLevelWarn:
			return @"WARN";
		case UXLogLevelError:
			return @"ERROR";
		case UXLogLevelFatal:
			return @"FATAL";
		default:
			return @"UNKNOWN";
	}
}

NSString* _GetLoggerName(UXLogger logger)
{
	switch (logger) 
	{
		case UXLoggerNone:
			return @"NONE";
		case UXLoggerSystem:
			return @"System";
		case UXLoggerUI:
			return @"UI";
		case UXLoggerApplicationDefault:
			return @"Application";
		default:
			return logger < UXLoggerSystemReserved 
			? @"UXInternal" : GetApplicationLoggerName(logger);
	}
}

//If a custom GetApplicationLoggerName is not redefined the default behaviour is to get the int value 
NSString* UXGetApplicationLoggerName(UXLogger logger)
{
	return [NSString stringWithFormat:@"%d",logger];
}

NSString* _UXGetLogPrefix(UXLogLevel logLevel, UXLogger logger)
{
	return [NSString stringWithFormat:@"[%@(%@)]", _GetLogLevelName(logLevel), _GetLoggerName(logger)];
}

void UXDetailLogMessage(UXLogLevel logLevel, 
				  UXLogger logger, 
				  const char* magicFile,
				  const char* magicFuncName,
				  int magicLineNumber,
				  NSString* message)
{
	//if not logging this level, skip...
	if ((UX_LOG_LEVELS	& logLevel) != logLevel) return; 
	
	//if not logging this logger, skip...
	if ((UX_LOG_LOGGERS & logger) != logger) return; 
	
//	const char* threadName = [[[NSThread currentThread] name] UTF8String];
//	NSString* magicFileName = [[NSString stringWithUTF8String:magicFile] lastPathComponent];

	NSString* logPrefix = _UXGetLogPrefix(logLevel, logger);

	NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
	[dateFormatter setDateFormat:@"hh:mm:ss"];
	
	NSLog(@"[%@]%@ %@:(%d)>  %@", 
		  [dateFormatter stringFromDate:[NSDate date]],
		  logPrefix,
		  [NSString stringWithCString: magicFuncName],
		  magicLineNumber, 
		  message);
	
	[dateFormatter release];
}

void UXDetailLog(UXLogLevel logLevel, 
				 UXLogger logger, 
				 const char* magicFileName,
				 const char* magicFuncName,
				 int magicLineNumber,
				 NSString* format, 
				 ...)
{
	va_list args;
	va_start (args, format);
	NSString* message =  [[NSString alloc] initWithFormat: format arguments: args];
	va_end (args);
	
	UXDetailLogMessage(logLevel, logger, magicFileName, magicFuncName, magicLineNumber, message);
	
	[message release];
}

void _UXLog(UXLogLevel logLevel, UXLogger logger, NSString* message)
{
	//if not logging this level, skip...
	if ((UX_LOG_LEVELS	& logLevel) != logLevel) return; 
	
	//if not logging this logger, skip...
	if ((UX_LOG_LOGGERS & logger) != logger) return; 
	
	//If we get to here we're all clear to log
	//build up a prefix containing LogLevel and Logger, e.g:
	//[DEBUG(System)]: message, [INFO(10)]: message, etc
	NSString* logPrefix = _UXGetLogPrefix(logLevel, logger);
	
	NSString* messageWithPrefix = [NSString stringWithFormat:@"%@: %@", logPrefix, message];	
	NSLog(messageWithPrefix);
}

//default logger is Debug
void UXLog(UXLogLevel logLevel, UXLogger logger, NSString* format, ...)
{
	va_list args;
	va_start (args, format);
	NSString* message =  [[NSString alloc] initWithFormat: format arguments: args];
	va_end (args);

	_UXLog(logLevel, logger, message);
	
	[message release];
}
